
#include "stdafx.h"

#include "gl/glew.h"

#include "CImg.h"
#include "testmesh.h"

TestMesh::TestMesh()
{
#if 0
    GLint bi=glGetUniformBlockIndex(m_simpProg, "Matrices");
    GLint size;
    glGetActiveUniformBlockiv(m_simpProg, bi, GL_UNIFORM_BLOCK_DATA_SIZE, &size);
    const char* names[]={"Matrices.Projection", "Camera", "NormalC"};
    GLuint indices[3];
    glGetUniformIndices(m_simpProg, 3, names, indices);
    GLint offsets[3];
    glGetActiveUniformsiv(m_simpProg, 3, indices, GL_UNIFORM_OFFSET, offsets);
#endif

    glGenVertexArrays(1, &m_vaoId);

    glGenBuffers(3, m_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
    const GLfloat vArr[] = {
        -1.0f, -1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 0.0f, 1.0f,
        -1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
    };
    glBufferData(GL_ARRAY_BUFFER, sizeof(vArr), vArr, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
    const GLfloat nArr[] = {
        -0.0990148f, -0.0990148f, 0.990148f,
        0.0990148f, -0.0990148f, 0.990148f,
        -0.0990148f, 0.0990148f, 0.990148f,
        0.0990148f, 0.0990148f, 0.990148f,
    };
    glBufferData(GL_ARRAY_BUFFER, sizeof(nArr), nArr, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo[2]);
    const GLfloat tArr[] = {
        0.0f, 0.0f,
        1.0f, 0.0f,
        0.0f, 1.0f,
        1.0f, 1.0f,
    };
    glBufferData(GL_ARRAY_BUFFER, sizeof(tArr), tArr, GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    using namespace cimg_library;
    CImg<unsigned char> image("assets/lena.bmp");
    GLsizei iWidth=image.width();
    GLsizei iHeight=image.height();
    image.mirror('y');  // mirror the image to suite GL texture axes
    image.permute_axes("cxyz");     // Permute axes to GL axes: (X,Y,Z,C)-->(C,X,Y,Z)
    glGenTextures(1, &m_Texture);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_Texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, iWidth, iHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, image.data());
    glGenerateMipmap(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, 0);

    m_modelData.ModelView(2,3)=-4.0f;
    m_modelData.ModelView.NormalMatrix(m_modelData.NormalM);
}

TestMesh::~TestMesh()
{
    glDeleteBuffers(sizeof(m_vbo)/sizeof(m_vbo[0]), m_vbo);
    glDeleteVertexArrays(1, &m_vaoId);
    glDeleteTextures(1, &m_Texture);
}

void TestMesh::Draw(const PresentTechnique* pTechnique)
{
    m_uniformModel->SetData(&m_modelData);
    m_uniformModel->Update();

    pTechnique->SetImgTexture(m_Texture);

    glBindVertexArray(m_vaoId);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}

void TestMesh::AttachUniforms(const UniformMap& uBlocks)
{
    m_uniformModel=static_cast<const ModelBlock*>(uBlocks.at("Model"));
}

void TestMesh::MapAttributes(const ProgramsMap& tMap)
{
    const PresentTechnique* pTechnique=static_cast<const PresentTechnique*>(tMap.at("Present"));

    glBindVertexArray(m_vaoId);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo[0]);
    m_Position=pTechnique->GetAttribLocation("Position");
    glVertexAttribPointer(m_Position, 4, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(m_Position);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo[1]);
    m_Normal=pTechnique->GetAttribLocation("Normal");
    glVertexAttribPointer(m_Normal, 3, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(m_Normal);

    glBindBuffer(GL_ARRAY_BUFFER, m_vbo[2]);
    m_TexCoords=pTechnique->GetAttribLocation("TexCoords0");
    glVertexAttribPointer(m_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, NULL);
    glEnableVertexAttribArray(m_TexCoords);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);
}

MeshPresentMethod TestMesh::PresentMethod() const
{
    return PRESENT_SIMPLE;
}
